package com.efast.dmom.mgmt.service.les.impl;

import com.efast.cafe.framework.exception.ServiceException;
import com.efast.cafe.framework.jdbc.JdbcDao;
import com.efast.cafe.framework.util.SpringWebUtils;
import com.efast.dmom.mgmt.bean.les.GoodsReceiptBean;
import com.efast.dmom.mgmt.bean.master.LocDockBean;
import com.efast.dmom.mgmt.dao.les.*;
import com.efast.dmom.mgmt.dao.master.TrBasPartStorageDockDao;
import com.efast.dmom.mgmt.entity.les.*;
import com.efast.dmom.mgmt.entity.master.TrBasPartStorageDock;
import com.efast.dmom.mgmt.entity.mes.TeProductInbound;
import com.efast.dmom.mgmt.service.les.TwDocAsnHeaderService;
import com.efast.dmom.mgmt.utils.Assist;
import com.efast.dmom.mgmt.utils.CompareTo;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author chlp
 */
@Service("twDocAsnHeaderServiceImpl")
public class TwDocAsnHeaderServiceImpl implements TwDocAsnHeaderService {

	/**
	 * 收货单TW_DOC_ASN_HEADER
	 */
	private final TwDocAsnHeaderDao twDocAsnHeaderDao;
	/**
	 * 收货单TW_DOC_ASN_DETAILS
	 */
	private final TwDocAsnDetailsDao twDocAsnDetailsDao;
	/**
	 * 分配记录 TW_INBOUND_ALLOC_DETAIL
	 */
	private final TwInboundAllocDetailDao twInboundAllocDetailDao;
	/**
	 * 库存表 TW_INV_SKU_LOC_T_L
	 */
	private final TwInvSkuLoctlDao twInvSkuLoctlDao;
	/**
	 * 收货记录 TT_WHM_MATERIAL_RECEIVE
	 */
	private final TtWhmMaterialReceiveDao ttWhmMaterialReceiveDao;
	/**
	 * 供应商零件配送模式设置 tr_bas_part_suppl_pull
	 */
	private final TrBasPartSupplPullDao trBasPartSupplPullDao;
	/**
	 * 零件批次属性表 tw_bas_part_batch
	 */
	private final TwBasPartBatchDao twBasPartBatchDao;
	/**
	 * 零件仓储关系以及动态库位入库选择规则 tr_bas_part_storage
	 */
	private final TrBasPartStorageDao trBasPartStorageDao;
	/**
	 * 仓储关系与道口关系表 tr_bas_part_storage_dock
	 */
	private final TrBasPartStorageDockDao trBasPartStorageDockDao;
	/**
	 * 道口 tm_bas_dock
	 */
	private final TmBasDockDao tmBasDockDao;
	/**
	 * 零件收货批次属性序列表 tw_bas_lot_sequence
	 */
	private final TwBasLotSequenceDao twBasLotSequenceDao;
	/**
	 * 零件批次属性组头配置 tw_bas_part_batch_header
	 */
	private final TwBasPartBatchHeaderDao twBasPartBatchHeaderDao;

	private final CommonServiceDao commonServiceDao;

	@Qualifier("jdbcDao")
	@Autowired
	private JdbcDao jdbcDao;

	@Autowired
	public TwDocAsnHeaderServiceImpl(TwBasPartBatchHeaderDao twBasPartBatchHeaderDao,
			TwBasLotSequenceDao twBasLotSequenceDao, TmBasDockDao tmBasDockDao,
			TrBasPartStorageDockDao trBasPartStorageDockDao, TrBasPartStorageDao trBasPartStorageDao,
			TwBasPartBatchDao twBasPartBatchDao, TrBasPartSupplPullDao trBasPartSupplPullDao,
			TtWhmMaterialReceiveDao ttWhmMaterialReceiveDao, TwDocAsnHeaderDao twDocAsnHeaderDao,
			TwDocAsnDetailsDao twDocAsnDetailsDao, TwInboundAllocDetailDao twInboundAllocDetailDao,
			TwInvSkuLoctlDao twInvSkuLoctlDao, CommonServiceDao commonServiceDao) {
		this.twBasPartBatchHeaderDao = twBasPartBatchHeaderDao;
		this.twBasLotSequenceDao = twBasLotSequenceDao;
		this.tmBasDockDao = tmBasDockDao;
		this.trBasPartStorageDockDao = trBasPartStorageDockDao;
		this.trBasPartStorageDao = trBasPartStorageDao;
		this.twBasPartBatchDao = twBasPartBatchDao;
		this.trBasPartSupplPullDao = trBasPartSupplPullDao;
		this.ttWhmMaterialReceiveDao = ttWhmMaterialReceiveDao;
		this.twDocAsnHeaderDao = twDocAsnHeaderDao;
		this.twDocAsnDetailsDao = twDocAsnDetailsDao;
		this.twInboundAllocDetailDao = twInboundAllocDetailDao;
		this.twInvSkuLoctlDao = twInvSkuLoctlDao;
		this.commonServiceDao = commonServiceDao;
	}

	/**
	 * ASN HEADER单据创建[生成ASN序列号，ASN状态改为0(即新单)]
	 */
	@Override
	public int insertTwDocAsnHeader(TwDocAsnHeader value) {
		value.setSheetCreateTime(new Date());
		value.setCompanyCode(SpringWebUtils.getRequestCompany());
		// 生成ASN序列号，ASN状态改为0(即新单)
		String anode = jdbcDao.executeProcGetCode("tw_doc_asn_header", "efast");
		value.setAsnSheetNo(anode);
		// SN单证状态（新单0、部分收货1、收货完成2、拒绝收货3、收货取消4、单证关闭5）
		value.setAsnSheetStatus("0");
		value.setCreateUserType("1");
		// 创建用户类型(系统自动0，人工1)
		return twDocAsnHeaderDao.insertTwDocAsnHeader(value);
	}

	/**
	 * ASN HEADER的关闭[ASN状态改为5(即单证关闭)],需要关闭header对应的datails的状态。
	 */
	@Override
	public void updateTwDocAsnHeader(TwDocAsnHeader value, Assist assist) {
		// 1:更新HEADER的状态
		twDocAsnHeaderDao.updateTwDocAsnHeader(value, assist);
		// 2：查询datails对应header的数据
		Assist assist1 = new Assist();
		assist1.setRequires(Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", value.getTwDocAsnHeaderId()));
		List<TwDocAsnDetails> listTwDocAsnDetails = twDocAsnDetailsDao.selectTwDocAsnDetails(assist1);
		// 3：修改details的每一行的状态 。10 为关闭
		Assist assist2 = new Assist();
		assist2.setRequires(Assist.andEq("tw_doc_asn_details.line_status", "10"));
		for (TwDocAsnDetails listTwDocAsnDetail : listTwDocAsnDetails) {
			twDocAsnDetailsDao.updateTwDocAsnDetails(listTwDocAsnDetail, assist2);
		}
	}

	/**
	 *
	 * 确认收货 ASN HEADER的接收[ASN状态改为2(即收货完成) / 收货完成后在TW_INBOUND_ALLOC_DETAIL创建数据] 需要用到的表： 收货单
	 * TW_DOC_ASN_HEADER、TW_DOC_ASN_DETAILS，TW_INBOUND_ALLOC_DETAIL 收货记录 TT_WHM_MATERIAL_RECEIVE 分配记录
	 * TW_INBOUND_ALLOC_DETAIL 库存表 TW_INV_SKU_LOC_T_L
	 *
	 * @param goodsReceiptBean
	 *            goodsReceiptBean
	 */ 
	@Override
	public void headerReceive(GoodsReceiptBean goodsReceiptBean) {
		TwDocAsnHeader twDocAsnHeader = goodsReceiptBean.getTwDocAsnHeader();
		List<TwDocAsnDetails> reqListTwDocAsnDetails = goodsReceiptBean.getListTwDocAsnDetails();
		if (reqListTwDocAsnDetails == null || reqListTwDocAsnDetails.size() == 0) {
			throw new ServiceException(twDocAsnHeader.getAsnSheetNo() + "下没有details,收货失败");
		}
		// 对于【确认收货】而言，首先应该满足三个条件才能进行收货。
		// 【1】： 根据道口号查询对应的stage库位（库位使用类型位stage），如没有找到，提示无法收货，需要配置道口对应的stage库位
		// 1个道口 多个stage库位的情况下 按照入库优先级排序 1最高 9最低 如果入库优先级也没填 那么就按照库位名排序（升序） 选第一个即可
		List<LocDockBean> listLocDockBean = twDocAsnHeaderDao.queryLocByDock(twDocAsnHeader.getDockId());
		LocDockBean needLocDockBean = new LocDockBean();
		if (listLocDockBean.size() == 0) {
			throw new ServiceException(twDocAsnHeader.getDockNo() + "道口编号没有对应的stage库位");
		}
		// 查询的结果是按照优先级级 升序排列的。找出第一个优先级不为null的一条记录。
		boolean sortNull = false;
		String[] str = new String[listLocDockBean.size()];
		for (int i = 0; i < listLocDockBean.size(); i++) {
			LocDockBean locDockBean = listLocDockBean.get(i);
			str[i] = locDockBean.getStorage_no();
			if (locDockBean.getInbound_sort_no() != 0) {
				needLocDockBean = locDockBean;
				sortNull = true;
			}
		}
		// 说明排序都是为null，此时需要根据库位编码排序，找出一个。
		if (!sortNull) {
			str = CompareTo.strSort(str);
			for (LocDockBean locDockBean : listLocDockBean) {
				if (locDockBean.getStorage_no().equals(str[0])) {
					needLocDockBean = locDockBean;
				}
			}
		}

		// 【2】： 没有配置批次规则的零件不能收货
		// 查询datails对应header的数据
		List<TwDocAsnDetails> dbTwDocAsnDetails = twDocAsnDetailsDao.selectTwDocAsnDetails(new Assist(
				Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", twDocAsnHeader.getTwDocAsnHeaderId())));
		for (TwDocAsnDetails twDocAsnDetails : dbTwDocAsnDetails) {
			int count = twDocAsnHeaderDao.queryBatchByPartNoVersion(twDocAsnDetails.getPartNoVersion());
			if (count == 0) {
				throw new ServiceException(twDocAsnDetails.getPartNoVersion() + "零件号没有配置批次规则");
			}
		}

		// 【3】：根据零件安全库存，查找当前零件的最大库存量，如果待入库数量+现存的库存量（当前数量）>设置的最大库存量，那么报错，提示超过安全库存，无法收货
		// 这块在统一库存调整的地址已经做的处理
		// 零件安全属性 表 tw_bas_sku_min_max
		// 零件的安全库存可以不用设置，但是如果设置了，则必须的判断。
		// 当前 库存数量 cur_qty + asn_r_inb_qty

		// 【4】：判断ASN单证状态
		TwDocAsnHeader twDocAsnHeader2 = twDocAsnHeaderDao.selectTwDocAsnHeaderById(
				twDocAsnHeader.getTwDocAsnHeaderId());
		// ASN单证状态（新单0、部分收货1、收货完成2、拒绝收货3、收货取消4、单证关闭5）
		String asnSheetStatus = twDocAsnHeader2.getAsnSheetStatus();
		if ("2".equals(asnSheetStatus) || "3".equals(asnSheetStatus) || "4".equals(asnSheetStatus)
				|| "5".equals(asnSheetStatus)) {
			String errorMsg = "";
			if ("2".equals(asnSheetStatus)) {
				errorMsg = "收货完成";
			}
			if ("3".equals(asnSheetStatus)) {
				errorMsg = "拒绝收货";
			}
			if ("4".equals(asnSheetStatus)) {
				errorMsg = "收货取消";
			}
			if ("5".equals(asnSheetStatus)) {
				errorMsg = "单证关闭";
			}
			throw new ServiceException("ASN单证状态是:" + errorMsg + "。无法接收");
		}

		// 【5】：遍历header下的datails的数据
		// header是部分收货还是全部收货
		boolean ifCompetRe = false;
		for (TwDocAsnDetails reqListTwDocAsnDetail : reqListTwDocAsnDetails) {

			// INB_SERIAL_NO的值即 60 RECEIVE_PACK_SERIAL（收货包装流水号，也称托盘号），67
			// 数据库查询出来的detail
			TwDocAsnDetails twDocAsnDetails = null;
			for (TwDocAsnDetails dbTwDocAsnDetail : dbTwDocAsnDetails) {
				if (dbTwDocAsnDetail.getTwDocAsnDetailsId().equals(
						reqListTwDocAsnDetail.getTwDocAsnDetailsId())) {
					twDocAsnDetails = dbTwDocAsnDetail;
					break;
				}
			}
			if (twDocAsnDetails == null) {
				throw new ServiceException("");
			}

			// 零件安全属性 表 tw_bas_sku_min_max
			// 查询零件的安全库存，可能为null，零件的安全库存可以不用设置，但是如果设置了，则必须的判断。
			Integer maxCount = twDocAsnHeaderDao.queryMinMaxPartNoVersion(twDocAsnDetails.getPartNoVersion(),
					twDocAsnDetails.getTrBasPartSupplId());
			System.out.println(maxCount);

			// reqListTwDocAsnDetail  前台用户修改的detail数据
			// 预期收货数量
			Integer asnReqQty = twDocAsnDetails.getAsnReqQty();
			// 实际收货包装编号
			String receivePackageNo = reqListTwDocAsnDetail.getReceivePackageNo();
			// 实际收货数量 [前台用户可以手动修改的]
			Integer asnReceivedQty = reqListTwDocAsnDetail.getAsnReceivedQty();
			// 实际收货箱数[前台自动计算出来的]
			Integer asnPackageNum = reqListTwDocAsnDetail.getReceivePackageNum();
			// 实际收货包装容量 [前台用户可以手动修改的]
			Integer receivePackageQty = reqListTwDocAsnDetail.getReceivePackageQty();
			if (twDocAsnDetails.getAsnReqQty() < asnReceivedQty) {
				throw new ServiceException(twDocAsnDetails.getPartNoVersion() + "的零件号，实际收货数量不能大于预期收货数量");
			}
			if (twDocAsnDetails.getAsnPackageNum() < asnPackageNum) {
				throw new ServiceException(twDocAsnDetails.getPartNoVersion() + "的零件号，实际收货箱数不能大于预期收货箱数");
			}
			// 【6】：需要更新的detail数据。包括detail的状态，实际收货数量，实际收货箱数，实际收货包装容量
			TwDocAsnDetails twDocAsnDetails2 = new TwDocAsnDetails();
			twDocAsnDetails2.setTwDocAsnDetailsId(twDocAsnDetails.getTwDocAsnDetailsId());
			// 实际收货数量 [前台用户可以手动修改的]
			twDocAsnDetails2.setAsnReceivedQty(asnReceivedQty);
			// 实际收货箱数[前台自动计算出来的]
			twDocAsnDetails2.setReceivePackageNum(asnPackageNum);
			// 实际收货包装容量 [前台用户可以手动修改的]
			twDocAsnDetails2.setReceivePackageQty(receivePackageQty);
			// 实际收货包装编号
			twDocAsnDetails2.setReceivePackageNo(receivePackageNo);
			// 入库包装代码
			twDocAsnDetails2.setInboundPackNo(receivePackageNo);
			// 入库包装容量
			twDocAsnDetails2.setInboundPackQty(receivePackageQty);
			// 零件包装编号
			twDocAsnDetails2.setPartPackageNo(receivePackageNo);
			// 零件包装容量
			twDocAsnDetails2.setPartPackageNum(receivePackageQty);
			Date date = new Date();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String dateString1 = formatter.format(date);
			// 设置收货时间
			twDocAsnDetails2.setLotatt01(dateString1);
			// 订单行状态（新单0、部分收货1、完全收货2、拒绝收货3、收货取消4、分配完成5、分配失败6、部分分配7、上架完成8、部分上架9，关闭10）
			// 如果行是新单状态 并且 实际收货数量=0 。则还是新单状态。
			if ("0".equals(twDocAsnDetails.getLineStatus()) && asnReceivedQty == 0) {
				twDocAsnDetails2.setLineStatus("0");
			}
			// 如果行是新单状态 并且 实际收货数量!=0 。则把新单设置部分收货 或者 成完全收货。
			if ("0".equals(twDocAsnDetails.getLineStatus()) && asnReceivedQty != 0) {
				// 判断没一行的状态是什么。
				// 部分收货
				if (asnReqQty > asnReceivedQty) {
					twDocAsnDetails2.setLineStatus("1");
					ifCompetRe = true;
					// 完全收货 receivePackageQty*asnPackageNum==asnReceivedQty
				} else if (asnReqQty.equals(asnReceivedQty)) {
					twDocAsnDetails2.setLineStatus("2");
				}
			}
			// 对于部分收货的是不允许再次收货的
			if ("1".equals(twDocAsnDetails.getLineStatus())) {
				throw new ServiceException(reqListTwDocAsnDetail.getPartNoVersion() + "已经收货，不能再次收货");
			} else {
				twDocAsnDetailsDao.updateNonEmptyTwDocAsnDetailsById(twDocAsnDetails2);
			}  // 收货的时候需要更新detail的字段 结束

			// 【7】 ：向分配记录（TW_INBOUND_ALLOC_DETAIL）插入数据， 设置tw_inbound_alloc_detail一些特殊的字段
			// 分配记录表（TW_INBOUND_ALLOC_DETAIL）的实体类
			TwInboundAllocDetail twInboundAllocDetail = new TwInboundAllocDetail();
			BeanUtils.copyProperties(twDocAsnDetails, twInboundAllocDetail);
			// 入库包装代码
			twInboundAllocDetail.setInboundPackNo(receivePackageNo);
			// 入库包装容量
			twInboundAllocDetail.setInboundPackQty(receivePackageQty);
			// 状态（已分配0，已生成上架任务1，已完成上架2，部分上架3，无法分配4，关闭5，冲销6）
			twInboundAllocDetail.setItemStatus("4");
			// 对Alloca_detail的INB_SERIAL_NO，PART_PACK_SERIAL；根据不同的规则赋不同的值
			TrBasPartSupplPull trBasPartSupplPull2 = new TrBasPartSupplPull();
			trBasPartSupplPull2.setPartNoVersion(twDocAsnDetails.getPartNoVersion());
			trBasPartSupplPull2.setSupplNo(twDocAsnDetails.getSupplNo());
			trBasPartSupplPull2.setMarkStatus(0);
			// 根据零件号和零件供应商号在 供应商零件配送模式设置 表中找一条对应的关系
			TrBasPartSupplPull trBasPartSupplPull = trBasPartSupplPullDao.selectTrBasPartSupplPullByObj(
					trBasPartSupplPull2);
			if (trBasPartSupplPull == null) {
				throw new ServiceException("根据" + twDocAsnDetails.getPartNoVersion() + "零件号,无法查询到供应商零件配送模式设置");
			}
			// is_trace_sequence 流水号生成规则(0:全局包装流水号,1:按入库包装级别生成2:按零件库位生成)
			if ("0".equals(trBasPartSupplPull.getIsTraceSequence())) {
				// 取值为0时，Alloc表2个字段为空；
				// 库内跟踪流水号码
				twInboundAllocDetail.setInbSerialNo(null);
				// 零件包装流水号
				twInboundAllocDetail.setPartPackSerial(null);
			}
			if ("1".equals(trBasPartSupplPull.getIsTraceSequence())) {
				// 取值为1时，两个字段均为托盘号 RECEIVE_PACK_SERIAL===twDocAsnDetails.getReceivePackSerial()
				// 库内跟踪流水号码
				twInboundAllocDetail.setInbSerialNo(twDocAsnDetails.getReceivePackSerial());
				// 零件包装流水号
				twInboundAllocDetail.setPartPackSerial(twDocAsnDetails.getReceivePackSerial());
			}
			if ("2".equals(trBasPartSupplPull.getIsTraceSequence())) {
				// 取值为2时，INB_SERIAL_NO字段为托盘号，PART_PACK_SERIAL字段为零件包装流水号。
				// 库内跟踪流水号码
				twInboundAllocDetail.setInbSerialNo(twDocAsnDetails.getReceivePackSerial());
				// 零件包装流水号
				twInboundAllocDetail.setPartPackSerial(twDocAsnDetails.getPartPackSerial());
			}
			// 待上架数量.赋值为details表中的实际收货数量
			twInboundAllocDetail.setPreNboundQty(reqListTwDocAsnDetail.getAsnReceivedQty());
			// 实际上架数量
			twInboundAllocDetail.setActNboundQty(0);
			int preinbpacknum = reqListTwDocAsnDetail.getAsnReceivedQty() % reqListTwDocAsnDetail.getAsnPackageQty();
			// 如果余数==0 说明能够整除
			if (preinbpacknum == 0) {
				twInboundAllocDetail.setPreInbPackNum(
						// 待上架箱数
						reqListTwDocAsnDetail.getAsnReceivedQty() / reqListTwDocAsnDetail.getAsnPackageQty());
			} else {
				twInboundAllocDetail.setPreInbPackNum(
						// 待上架箱数
						(reqListTwDocAsnDetail.getAsnReceivedQty() / reqListTwDocAsnDetail.getAsnPackageQty()) + 1);
			}
			// 实际上架箱数
			twInboundAllocDetail.setActInbPackNum(0);

			// 生成零件批次号
			// 确认收货的时候 ===》生成零件批次号 ---每个零件维护的时候 ，都会默认生成6条
			// 零件批次属性，从主数据copy（tm_bas_batch，tm_bas_batch_group，tr_bas_batch_group_batch-多对多）来的。
			// 对应的业务表是：tw_bas_part_batch（主数据copy来的），tw_bas_part_batch_header
			// 根据 零件号和供应商号，查询零件批次属性。根据批次属性查询是否生成过批次号
			List<TwBasPartBatchHeader> listTwBasPartBatchHeader = twBasPartBatchHeaderDao.selectTwBasPartBatchHeader(
					new Assist(
							Assist.andEq("tw_bas_part_batch_header.part_no_version",
									twDocAsnDetails.getPartNoVersion()),
							Assist.andEq("tw_bas_part_batch_header.suppl_no", twDocAsnDetails.getSupplNo())));
			if (listTwBasPartBatchHeader.size() == 0) {
				throw new ServiceException("零件号：" + twDocAsnDetails.getPartNoVersion() + "供应商："
						+ twDocAsnDetails.getSupplNo() + "，没有对应的零件批次属性");
			}
			List<TwBasPartBatch> listTwBasPartBatch = twBasPartBatchDao.selectTwBasPartBatch(
					new Assist(Assist.andEq("tw_bas_part_batch.tw_bas_part_batch_header_id",
							listTwBasPartBatchHeader.get(0).getTwBasPartBatchHeaderId())));
			Date currentTime = new Date();
			SimpleDateFormat formatter1 = new SimpleDateFormat("yyyyMMdd");
			String dateString = formatter1.format(currentTime);
			StringBuilder lotCombStr = new StringBuilder();
			lotCombStr.append(twDocAsnDetails.getPartNoVersion());
			for (TwBasPartBatch twBasPartBatch : listTwBasPartBatch) {
				if ("LOTATT01".equals(twBasPartBatch.getBatchOrder()) && "1".equals(twBasPartBatch.getIsUsedforLot())) {
					lotCombStr.append("-").append(dateString);
				}
				if ("LOTATT02".equals(twBasPartBatch.getBatchOrder()) && "1".equals(twBasPartBatch.getIsUsedforLot())) {
					lotCombStr.append("-").append(listTwBasPartBatchHeader.get(0).getPlantNo());
				}
				if ("LOTATT03".equals(twBasPartBatch.getBatchOrder()) && "1".equals(twBasPartBatch.getIsUsedforLot())) {
					lotCombStr.append("-").append(listTwBasPartBatchHeader.get(0).getWorkshopNo());
				}
				if ("LOTATT04".equals(twBasPartBatch.getBatchOrder()) && "1".equals(twBasPartBatch.getIsUsedforLot())) {
					lotCombStr.append("-").append(listTwBasPartBatchHeader.get(0).getSupplNo());
				}
				if ("LOTATT05".equals(twBasPartBatch.getBatchOrder())) {
					if ("1".equals(twBasPartBatch.getIsUsedforLot())) {
						lotCombStr.append("-" + "1");
					} else {
						lotCombStr.append("-" + "0");
					}
				}
			}
			// 零件批次号
			String lotNo;
			List<TwBasLotSequence> listTwBasLotSequence = twBasLotSequenceDao.selectTwBasLotSequence(
					new Assist(Assist.andEq("tw_bas_lot_sequence.lot_comb_str", lotCombStr.toString())));
			// 说明没有相同批次的零件
			if (listTwBasLotSequence.size() == 0) {
				TwBasLotSequence twbaslotsequence = new TwBasLotSequence();
				twbaslotsequence.setLotCombStr(lotCombStr.toString());
				lotNo = jdbcDao.executeProcGetCode("tw_bas_lot_sequence", "efast");
				twbaslotsequence.setLotCurSeq(lotNo);
				twbaslotsequence.setMarkStatus(1);
				twbaslotsequence.setCompanyCode(SpringWebUtils.getRequestCompany());
				twbaslotsequence.setCreateTime(new Date());
				twbaslotsequence.setCreateUser(SpringWebUtils.getRequestUser());
				twBasLotSequenceDao.insertNonEmptyTwBasLotSequence(twbaslotsequence);
			} else {
				lotNo = listTwBasLotSequence.get(0).getLotCurSeq();
			}
			twInboundAllocDetail.setLotNo(lotNo);
			// 任务创建人
			twInboundAllocDetail.setTaskCreateman(SpringWebUtils.getRequestUser());
			// 任务创建时间
			twInboundAllocDetail.setTaskCreatetime(new Date());
			// stage库位
			twInboundAllocDetail.setStageBasStorageId(needLocDockBean.getTm_bas_loc_id());
			// 分配类型（收货上架分配0，补货任务分配1，翻包任务分配2）
			twInboundAllocDetail.setAllocType("0");
			twInboundAllocDetail.setPreTmBasStorageId(needLocDockBean.getTm_bas_loc_id());
			twInboundAllocDetail.setPreTmBasStorageNo(needLocDockBean.getStorage_no());
			twInboundAllocDetailDao.insertNonEmptyTwInboundAllocDetail(twInboundAllocDetail);

			// 【8】:向库存表(TW_INV_SKU_LOC_T_L)中插入一条数据。库位类型是【待收货库位】，即是收货的缓存区。
			TwInvSkuLoctl twInvSkuLoctl = new TwInvSkuLoctl();
			BeanUtils.copyProperties(twInboundAllocDetail, twInvSkuLoctl);
			twInvSkuLoctl.setTmBasStorageId(needLocDockBean.getTm_bas_loc_id());
			// 箱数
			twInvSkuLoctl.setPackageNum(1);
			// 可用数量
			twInvSkuLoctl.setAvailableQty(asnReceivedQty);
			// 库存数量
			twInvSkuLoctl.setCurQty(asnReceivedQty);
			// 待入库数量
			twInvSkuLoctl.setrInbQty(0);
			// ASN待入库上架数量-ASN_R_INB_QTY
			twInvSkuLoctl.setAsnrInbQty(0);
			TwInvSkuLoctl twInvSkuLoctl1 = commonServiceDao.queryWhDlocLoc(needLocDockBean.getTm_bas_loc_id());
			twInvSkuLoctl.setLocNo(twInvSkuLoctl1.getLocNo());
			twInvSkuLoctl.setDlocNo(twInvSkuLoctl1.getDlocNo());
			twInvSkuLoctl.setWarehouseNo(twInvSkuLoctl1.getWarehouseNo());
			twInvSkuLoctl.setCompanyCode(SpringWebUtils.getRequestCompany());
			twInvSkuLoctl.setCreateUser(SpringWebUtils.getRequestUser());
			twInvSkuLoctl.setCreateTime(new Date());
			twInvSkuLoctl.setMarkStatus(1);
			twInvSkuLoctlDao.insertNonEmptyTwInvSkuLoctl(twInvSkuLoctl);

			// 【9】:向收货记录(TT_WHM_MATERIAL_RECEIVE)中 插入数据
			TtWhmMaterialReceive ttWhmMaterialReceive = new TtWhmMaterialReceive();
			BeanUtils.copyProperties(twInboundAllocDetail, ttWhmMaterialReceive);
			// 零件供应商关系ID
			ttWhmMaterialReceive.setTrBasPartSupplId(twDocAsnDetails.getTrBasPartSupplId());
			// 接收数量
			ttWhmMaterialReceive.setReceiveQty(twDocAsnDetails.getAsnReceivedQty());
			// 接收人
			ttWhmMaterialReceive.setReceiveUsername(SpringWebUtils.getRequestUser());
			// 接收时间
			ttWhmMaterialReceive.setReceiveTime(new Date());
			// 接收道口编号
			ttWhmMaterialReceive.setReceiveDockId(twDocAsnHeader.getDockId());
			ttWhmMaterialReceive.setPartLotAttr1(twDocAsnDetails.getLotatt01());
			ttWhmMaterialReceive.setPartLotAttr2(twDocAsnDetails.getLotatt02());
			ttWhmMaterialReceive.setPartLotAttr3(twDocAsnDetails.getLotatt03());
			ttWhmMaterialReceive.setPartLotAttr4(twDocAsnDetails.getLotatt04());
			ttWhmMaterialReceive.setPartLotAttr5(twDocAsnDetails.getLotatt05());
			// ASN单证类型（供应商到货1、3PL到货2、退货3）
			ttWhmMaterialReceive.setCommonSheetType("1");
			// 对应单证编号
			ttWhmMaterialReceive.setSheetNo(twDocAsnHeader.getAsnSheetNo());
			// 是否已分配（0未分配，1部分分配，2已分配）
			ttWhmMaterialReceive.setInboundStatus(0);
			// ttWhmMaterialReceive.setSheetId(sheetId);// 对应单证ID
			// 入库组号（用户名加当前时间）
			ttWhmMaterialReceive.setInBoundGroupId(SpringWebUtils.getRequestUser() + new Date());
			// ttWhmMaterialReceive.setSheetItem(sheetItem); // 配送单物料子表行(采购单使用)
			// ttWhmMaterialReceive.setWarehouseId(warehouseId);// 拣货仓库
			// ttWhmMaterialReceive.setDlocId(dlocId); // 库区
			// ttWhmMaterialReceive.setLocId(locId); // 库位
			// ttWhmMaterialReceive.setDlocPackageSysid(dlocPackageSysid);// 存储包装代码
			// ttWhmMaterialReceive.setCurPackageNum(curPackageNum); //当前箱数
			// ttWhmMaterialReceive.setReceiveNote(receiveNote);// 收货备注
			// ttWhmMaterialReceive.setTmBasDeliveryUnitId(twDocAsnHeader.getDeliveryRec());//
			// 收货地
			// ttWhmMaterialReceive.setSxCardNo(sxCardNo); // 随箱卡号 托盘号/库存跟踪号
			// ttWhmMaterialReceive.setDeliverySend(twDocAsnHeader.getDeliverySend()); //
			// 发货地
			ttWhmMaterialReceive.setPartNoVersion(twDocAsnDetails.getPartNoVersion());
			ttWhmMaterialReceive.setSupplNo(twDocAsnDetails.getSupplNo());
			ttWhmMaterialReceive.setAsnSheetNo(twDocAsnHeader.getAsnSheetNo());
			ttWhmMaterialReceive.setTwDocAsnDetailsId(twDocAsnDetails.getTwDocAsnDetailsId());
			ttWhmMaterialReceive.setCompanyCode(SpringWebUtils.getRequestCompany());
			ttWhmMaterialReceive.setCreateUser(SpringWebUtils.getRequestUser());
			ttWhmMaterialReceive.setCreateTime(new Date());
			ttWhmMaterialReceive.setMarkStatus(1);
			ttWhmMaterialReceive.setRandNo("111");
			ttWhmMaterialReceiveDao.insertNonEmptyTtWhmMaterialReceive(ttWhmMaterialReceive);
		} // 遍历detail结束

		// 【11】：设置header是部分收货还是全部收货
		TwDocAsnHeader twDocAsnHeader1 = new TwDocAsnHeader();
		twDocAsnHeader1.setTwDocAsnHeaderId(twDocAsnHeader.getTwDocAsnHeaderId());
		List<TwDocAsnDetails> dbTwDocAsnDetails001 = twDocAsnDetailsDao.selectTwDocAsnDetails(new Assist(
				Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", twDocAsnHeader.getTwDocAsnHeaderId())));
		if (!ifCompetRe && reqListTwDocAsnDetails.size() == dbTwDocAsnDetails.size()) {
			twDocAsnHeader1.setAsnSheetStatus("2");
		} else {
			if(dbTwDocAsnDetails.size()!=0) {
				boolean flag =true;
				for(TwDocAsnDetails twDocAsnDetails:dbTwDocAsnDetails001) {
					if(!twDocAsnDetails.getLineStatus().equals("2")) {
						flag = false;
					}
				}
				if(flag) {
					twDocAsnHeader1.setAsnSheetStatus("2");
				}else {
					twDocAsnHeader1.setAsnSheetStatus("1");
				}
			}
		}
		twDocAsnHeaderDao.updateNonEmptyTwDocAsnHeaderById(twDocAsnHeader1);
	}

	/**
	 * HEADER的的拒绝:[ASN状态改为3(即收货拒绝)]
	 * 
	 * @param value
	 *            value
	 * @param assist
	 *            assist
	 */
	@Override
	public void refuseReceive(TwDocAsnHeader value, Assist assist) {
		TwDocAsnHeader twDocAsnHeader = twDocAsnHeaderDao.selectTwDocAsnHeaderById(value.getTwDocAsnHeaderId());
		// 点击“拒收”即拒绝收货，单据状态（Header和Detail）改成拒绝收货。仅新单状态下可以拒绝。
		if (!"0".equals(twDocAsnHeader.getAsnSheetStatus())) {
			throw new ServiceException("仅新单状态下可以拒绝");
		}
		// 1:更新HEADER的状态
		twDocAsnHeaderDao.updateNonEmptyTwDocAsnHeaderById(value);
		// 2：查询datails对应header的数据
		Assist assist1 = new Assist();
		assist1.setRequires(Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", value.getTwDocAsnHeaderId()));
		List<TwDocAsnDetails> listTwDocAsnDetails = twDocAsnDetailsDao.selectTwDocAsnDetails(assist1);
		for (TwDocAsnDetails twDocAsnDetails : listTwDocAsnDetails) {
			// 新单0、部分收货1、完全收货2、拒绝收货3、收货取消4、分配完成5、分配失败6、部分分配7、上架完成8、部分上架9，关闭10
			// 3:更新details表中的没行的状态。
			twDocAsnDetails.setLineStatus("3");
			twDocAsnDetailsDao.updateNonEmptyTwDocAsnDetailsById(twDocAsnDetails);
		}
	}

	/**
	 * 取消收货操作[ASN状态改为4(收货取消)-只有部分收货/收货完成才能取消]
	 * 
	 * @param value
	 *            value
	 */
	@Override
	public void cancelTheReceiptOfTheGoods(TwDocAsnHeader value) {
		try {
			TwDocAsnHeader twDocAsnHeader = twDocAsnHeaderDao.selectTwDocAsnHeaderById(value.getTwDocAsnHeaderId());
			if ("1".equals(twDocAsnHeader.getAsnSheetStatus()) || "2".equals(twDocAsnHeader.getAsnSheetStatus())) {
				// 1：更新header的状态
				value.setAsnSheetStatus("0");
				twDocAsnHeaderDao.updateNonEmptyTwDocAsnHeaderById(value);
				// 2：查询header在details表中的对应数据 1对n
				Assist assist3 = new Assist();
				assist3.setRequires(
						Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", value.getTwDocAsnHeaderId()));
				List<TwDocAsnDetails> listTwDocAsnDetails = twDocAsnDetailsDao.selectTwDocAsnDetails(assist3);
				// 3:更新details表中的状态
				for (TwDocAsnDetails twDocAsnDetails : listTwDocAsnDetails) {
					String lineStatus = twDocAsnDetails.getLineStatus();
					// ASN Detail中只要有1条3、4、8、9、10的状态，则不能取消收货
					if ("3".equals(lineStatus) || "4".equals(lineStatus) || "8".equals(lineStatus)
							|| "9".equals(lineStatus) || "10".equals(lineStatus)) {
						System.out.println();
					} else {
						// ASN Detail还原，Alloc表清空、上架任务表、待上架库存清空；
						twDocAsnDetails.setLineStatus("0");
						Assist assist = new Assist(Assist.andEq("tw_inbound_alloc_detail.tw_doc_asn_details_id",
								twDocAsnDetails.getTwDocAsnDetailsId()));
						twInboundAllocDetailDao.deleteTwInboundAllocDetail(assist);
					}
					twDocAsnDetailsDao.updateNonEmptyTwDocAsnDetailsById(twDocAsnDetails);
				}
			} else {
				throw new ServiceException("只有部分收货/收货完成才能取消");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServiceException(e.getMessage());
		}
	}

	@Override
	public int updateNonEmptyTwDocAsnHeaderById(TwDocAsnHeader enti) {
		// 任何状态下均可以关闭单据，关闭后不能进行任何操作、删除相关数据
		// （待上架库存、待收货区库存、可用库存、当前库存、Alloc表、上架任务表）。关闭ASN时同时关闭ASN Detail。
		Assist assist = new Assist(Assist.andEq("tw_doc_asn_details.tw_doc_asn_header_id", enti.getTwDocAsnHeaderId()));
		TwDocAsnDetails twDocAsnDetails = new TwDocAsnDetails();
		twDocAsnDetails.setLineStatus("5");
		twDocAsnDetailsDao.updateNonEmptyTwDocAsnDetails(twDocAsnDetails, assist);
		return twDocAsnHeaderDao.updateNonEmptyTwDocAsnHeaderById(enti);
	}

	/**
	 * 成品入库新增
	 * 
	 * @param teProductInbound
	 *            teProductInbound
	 * @return 1
	 */
	@Override
	public int insertTwDocAsnHeaderByJob(TeProductInbound teProductInbound) {

		List<TrBasPartStorage> selectTrBasPartStorage = trBasPartStorageDao.selectTrBasPartStorage(
				new Assist(Assist.andEq("part_no_version", teProductInbound.getPartNoVersion()),
						Assist.andEq("plant_no", teProductInbound.getPlantNo()),
						Assist.andEq("workshop_no", teProductInbound.getWorkshopNo())));
		if (selectTrBasPartStorage.size() == 0) {
			throw new ServiceException(teProductInbound.getPartNoVersion() + "没有对应的仓库关系");
		}

		List<TrBasPartStorageDock> selectTrBasPartStorageDock = trBasPartStorageDockDao.selectTrBasPartStorageDock(
				new Assist(
						Assist.andEq("tr_bas_part_storage_id", selectTrBasPartStorage.get(0).getTrBasPartStorageId()),
						Assist.andEq("dock_type", "0")));

		TwDocAsnHeader value = new TwDocAsnHeader();
		value.setDockId(selectTrBasPartStorageDock.get(0).getTmBasDockId());
		TmBasDock selectTmBasDockById = tmBasDockDao.selectTmBasDockById(
				selectTrBasPartStorageDock.get(0).getTmBasDockId());
		value.setDockNo(selectTmBasDockById.getDockNo());
		value.setSheetCreateTime(new Date());
		// ASN单证类型（供应商到货1、3PL到货2、退货3,成品入库4）
		value.setCommonSheetType("4");
		// 生成ASN序列号，ASN状态改为0(即新单)
		String aSNode = jdbcDao.executeProcGetCode("tw_doc_asn_header", "efast");
		value.setAsnSheetNo(aSNode);
		// SN单证状态（新单0、部分收货1、收货完成2、拒绝收货3、收货取消4、单证关闭5）
		value.setAsnSheetStatus("0");
		value.setCreateUserType("1");
		// 创建用户类型(系统自动0，人工1)
		twDocAsnHeaderDao.insertTwDocAsnHeader(value);
		return value.getTwDocAsnHeaderId();
	}

	@Override
	public long getTwDocAsnHeaderRowCount(Assist assist) {
		return twDocAsnHeaderDao.getTwDocAsnHeaderRowCount(assist);
	}

	@Override
	public List<TwDocAsnHeader> selectTwDocAsnHeader(Assist assist) {
		return twDocAsnHeaderDao.selectTwDocAsnHeader(assist);
	}

	@Override
	public TwDocAsnHeader selectTwDocAsnHeaderByObj(TwDocAsnHeader obj) {
		return twDocAsnHeaderDao.selectTwDocAsnHeaderByObj(obj);
	}

	@Override
	public TwDocAsnHeader selectTwDocAsnHeaderById(Integer id) {
		return twDocAsnHeaderDao.selectTwDocAsnHeaderById(id);
	}

	@Override
	public int insertNonEmptyTwDocAsnHeader(TwDocAsnHeader value) {
		return twDocAsnHeaderDao.insertNonEmptyTwDocAsnHeader(value);
	}

	@Override
	public int insertTwDocAsnHeaderByBatch(List<TwDocAsnHeader> value) {
		return twDocAsnHeaderDao.insertTwDocAsnHeaderByBatch(value);
	}

	@Override
	public int deleteTwDocAsnHeaderById(Integer id) {
		return twDocAsnHeaderDao.deleteTwDocAsnHeaderById(id);
	}

	@Override
	public int deleteTwDocAsnHeader(Assist assist) {
		return twDocAsnHeaderDao.deleteTwDocAsnHeader(assist);
	}

	@Override
	public int updateTwDocAsnHeaderById(TwDocAsnHeader enti) {
		return twDocAsnHeaderDao.updateTwDocAsnHeaderById(enti);
	}

	@Override
	public int updateNonEmptyTwDocAsnHeader(TwDocAsnHeader value, Assist assist) {
		return twDocAsnHeaderDao.updateNonEmptyTwDocAsnHeader(value, assist);
	}

}